from flask import Blueprint, request, current_app
from datetime import datetime
import xml.etree.ElementTree as ET
import hashlib
import uuid

from models import db, User, WechatAccount, WechatQrCode
from utils import WechatUtil

wechat_bp = Blueprint('wechat', __name__)

def verify_signature(signature, timestamp, nonce, token):
    """验证微信签名"""
    tmp_arr = [token, timestamp, nonce]
    tmp_arr.sort()
    tmp_str = ''.join(tmp_arr)
    tmp_str = hashlib.sha1(tmp_str.encode()).hexdigest()
    return tmp_str == signature

def parse_xml_message(xml_data):
    """解析XML消息"""
    try:
        root = ET.fromstring(xml_data)
        msg = {}
        for child in root:
            msg[child.tag] = child.text
        return msg
    except Exception as e:
        print(f"解析XML消息失败: {str(e)}")
        return None

@wechat_bp.route('/callback', methods=['GET', 'POST'])
def wechat_callback():
    """微信公众号回调处理"""
    if request.method == 'GET':
        # 验证服务器配置
        signature = request.args.get('signature')
        timestamp = request.args.get('timestamp')
        nonce = request.args.get('nonce')
        echostr = request.args.get('echostr')
        
        token = current_app.config.get('WECHAT_TOKEN')
        
        if verify_signature(signature, timestamp, nonce, token):
            return echostr
        else:
            return 'Invalid signature', 403
    
    elif request.method == 'POST':
        # 处理微信消息
        xml_data = request.data
        msg = parse_xml_message(xml_data)
        
        if not msg:
            return 'Invalid message format', 400
        
        msg_type = msg.get('MsgType')
        from_user = msg.get('FromUserName')
        to_user = msg.get('ToUserName')
        
        if msg_type == 'event':
            event = msg.get('Event')
            
            if event == 'subscribe':
                # 用户关注事件
                handle_subscribe_event(from_user, msg)
            
            elif event == 'SCAN':
                # 扫描二维码事件
                handle_scan_event(from_user, msg)
            
            elif event == 'unsubscribe':
                # 用户取消关注事件
                handle_unsubscribe_event(from_user)
        
        # 返回空字符串表示处理成功
        return ''

def handle_subscribe_event(openid, msg):
    """处理关注事件"""
    try:
        # 获取微信用户信息
        wechat_util = WechatUtil(
            current_app.config.get('WECHAT_APP_ID'),
            current_app.config.get('WECHAT_APP_SECRET'),
            current_app.config.get('WECHAT_TOKEN')
        )
        
        user_info = wechat_util.get_user_info(openid)
        
        # 查找或创建微信账号记录
        wechat_account = WechatAccount.query.filter_by(openid=openid).first()
        
        if not wechat_account:
            # 创建新用户
            user = User(
                uuid=str(uuid.uuid4()),
                nickname=user_info.get('nickname', f'微信用户{openid[-6:]}'),
                avatar=user_info.get('headimgurl')
            )
            db.session.add(user)
            db.session.flush()
            
            # 创建微信账号记录
            wechat_account = WechatAccount(
                user_id=user.id,
                openid=openid,
                unionid=user_info.get('unionid'),
                nickname=user_info.get('nickname'),
                avatar=user_info.get('headimgurl'),
                subscribe_status=1,
                subscribe_time=datetime.utcnow()
            )
            db.session.add(wechat_account)
        else:
            # 更新关注状态
            wechat_account.subscribe_status = 1
            wechat_account.subscribe_time = datetime.utcnow()
            wechat_account.nickname = user_info.get('nickname')
            wechat_account.avatar = user_info.get('headimgurl')
        
        # 检查是否是扫码关注
        event_key = msg.get('EventKey')
        if event_key and event_key.startswith('qrscene_'):
            scene_id = event_key[8:]  # 去掉 'qrscene_' 前缀
            handle_qr_scan(openid, scene_id)
        
        db.session.commit()
        
    except Exception as e:
        print(f"处理关注事件失败: {str(e)}")
        db.session.rollback()

def handle_scan_event(openid, msg):
    """处理扫码事件"""
    try:
        event_key = msg.get('EventKey')
        if event_key:
            handle_qr_scan(openid, event_key)
    except Exception as e:
        print(f"处理扫码事件失败: {str(e)}")

def handle_qr_scan(openid, scene_id):
    """处理二维码扫描"""
    try:
        # 查找二维码记录
        qr_code = WechatQrCode.query.filter_by(scene_id=scene_id).first()
        
        if not qr_code or qr_code.is_expired():
            return
        
        # 查找微信账号
        wechat_account = WechatAccount.query.filter_by(openid=openid).first()
        
        if not wechat_account:
            return
        
        # 更新二维码状态
        qr_code.status = 'confirmed'
        qr_code.user_id = wechat_account.user_id
        qr_code.updated_at = datetime.utcnow()
        
        db.session.commit()
        
    except Exception as e:
        print(f"处理二维码扫描失败: {str(e)}")
        db.session.rollback()

def handle_unsubscribe_event(openid):
    """处理取消关注事件"""
    try:
        wechat_account = WechatAccount.query.filter_by(openid=openid).first()
        if wechat_account:
            wechat_account.subscribe_status = 0
            db.session.commit()
    except Exception as e:
        print(f"处理取消关注事件失败: {str(e)}")
        db.session.rollback()